﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace FandangoAids
{
    public partial class YahooAids : Form
    {
        Communications communications = new Communications();
        Random ran = new Random();
        BackgroundWorker worker = new BackgroundWorker();
        ReviewData reviewData = new ReviewData();
        int progressValue = 0;
        string status = "Status: Waiting";

        enum ReviewResult { Successful, Failed, AlreadyReviewed };

        class ReviewData
        {
            public string MovieID { get; set; }
            public string ReviewTitle { get; set; }
            public string ReviewText { get; set; }
            public string[] Login { get; set; }
        }

        public YahooAids()
        {
            CheckForIllegalCrossThreadCalls = false;
            Storage.Load();
            InitializeComponent();
            comboBoxMovieID.Text = Storage.MovieID;
            richTextBoxDomain.Text = Storage.DomainSpins;
            LoadItemFromID();
            worker.DoWork += worker_DoWork;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
            new Timer { Interval = 100, Enabled = true }.Tick += progressUpdater_Tick;
            ActiveControl = textBoxLogin;
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            buttonInitiate.Enabled = true;
        }

        void progressUpdater_Tick(object sender, EventArgs e)
        {
            labelStatus.Text = status;
            progressBar1.Value = progressValue;
        }

        void UpdateStatus(string update)
        {
            status = "Status: " + update;
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            progressValue = 0;
            if (Login())
            {
                UpdateStatus("Logged in with " + reviewData.Login[0]);
                progressValue = 1;
                var reviewResult = PostReview();
                switch (reviewResult)
                {
                    case ReviewResult.Successful:
                        SerializableDictionary<string, string> links = new SerializableDictionary<string, string>();
                        links.Add(reviewData.MovieID, string.Format("http://movies.yahoo.com/mvc/drv?mid={0}&s=rc_d", reviewData.MovieID.Split(':')[0]));
                        log1.PerformLog("Posted review on {LINK} with " + string.Join(":", reviewData.Login), links, WriteEntry: true);
                        progressValue = 2;
                        UpdateStatus("Completed");
                        return;
                    case ReviewResult.AlreadyReviewed:
                        UpdateStatus(string.Format("Already posted review on {0} with {1}", reviewData.MovieID, reviewData.Login[0]));
                        progressValue = 0;
                        return;
                    case ReviewResult.Failed:
                        UpdateStatus(string.Format("Failed to post review on {0} with {1}", reviewData.MovieID, reviewData.Login[0]));
                        progressValue = 0;
                        return;
                }
            }
            else
            {
                UpdateStatus("Failed logging in with " + reviewData.Login[0]);
                progressValue = 0;
            }

        }

        private void buttonInitiate_Click(object sender, EventArgs e)
        {
            reviewData.MovieID = comboBoxMovieID.Text;
            reviewData.ReviewTitle = textBoxTitle.Text;
            reviewData.ReviewText = textBoxReview.Text.Replace("{DOMAIN}", GetDomainSpin());
            reviewData.Login = textBoxLogin.Text.Split(':');
            buttonInitiate.Enabled = false;
            worker.RunWorkerAsync();
        }

        string GetDomainSpin()
        {
            string[] lines = richTextBoxDomain.Lines;
            string domain = "";

            for (int i = 0; i < lines[0].Length; i++)
            {
                domain = domain + lines[ran.Next(0, lines.Length)][i];
            }

            return domain;
        }

        bool Login()
        {
            communications.ClearCookies();

            string loginUrl = "https://login.yahoo.com/config/login?";
            string loginWebPage = communications.PerformGet(loginUrl);
            string dotU = Regex.Match(loginWebPage, "<input type=\"hidden\" name=\".u\" value=\"([^<]+)\">").Groups[1].Value;
            string dotChallenge = Regex.Match(loginWebPage, "<input type=\"hidden\" name=\".challenge\" value=\"([^<]+)\">").Groups[1].Value;

            var postData = new Communications.PostData();
            postData.AddValue(".tries", "1");
            postData.AddValue(".src", "");
            postData.AddValue(".md5", "");
            postData.AddValue(".hash", "");
            postData.AddValue(".js", "");
            postData.AddValue(".last", "");
            postData.AddValue("promo", "");
            postData.AddValue(".intl", "us");
            postData.AddValue(".bypass", "");
            postData.AddValue(".partner", "");
            postData.AddValue(".u", dotU);
            postData.AddValue(".v", "0");
            postData.AddValue(".challenge", "");
            postData.AddValue(".yplus", "");
            postData.AddValue(".emailCode", "");
            postData.AddValue("pkg", "");
            postData.AddValue("stepid", "");
            postData.AddValue(".ev", "");
            postData.AddValue("hasMsgr", "0");
            postData.AddValue(".chkP", "Y");
            postData.AddValue(".done", "http://my.yahoo.com");
            postData.AddValue(".pd", "_ver=0&c=&ivt=&sg=");
            postData.AddValue("pad", "3");
            postData.AddValue("aad", "3");
            postData.AddValue("login", reviewData.Login[0]);
            postData.AddValue("passwd", reviewData.Login[1]);
            postData.AddValue(".persistent", "y");
            postData.AddValue(".save", "");
            postData.AddValue("passwd_raw", "");
            var result = communications.PerformPost(loginUrl, postData, referer: loginUrl, allowAutoRedirect: true);

            return result.Contains("my.yahoo.com") || result.Contains("member");

        }

        ReviewResult PostReview()
        {
            string movieUrl = string.Format("http://movies.yahoo.com/movie/{0}/user", reviewData.MovieID.Split(':')[0]);
            string moviePage = communications.PerformGet(movieUrl);
            if (moviePage.Contains("You have reviewed this movie"))
                return ReviewResult.AlreadyReviewed;
            string writeReviewUrl = Regex.Match(moviePage, "<a href=\"([^<]+)\">Write your own review").Groups[1].Value;
            string reviewPage = communications.PerformGet(writeReviewUrl, referer: movieUrl);
            string mid = Regex.Match(reviewPage, "name=mid value=\"([^<]+)\"").Groups[1].Value;
            string revoid = Regex.Match(reviewPage, "name=revoid value=\"([^<]+)\"").Groups[1].Value;
            string mtitle = Regex.Match(reviewPage, "name=mtitle value=\"([^<]+)\"").Groups[1].Value;
            string crumb = Regex.Match(reviewPage, "name=\".crumb\" value=\"([^<]+)\"").Groups[1].Value;

            var data = new Communications.PostData();
            data.AddValue("mid", mid);
            data.AddValue("revoid", revoid);
            data.AddValue("mtitle", mtitle);
            data.AddValue(".crumb", crumb);
            data.AddValue("rtid", "");
            data.AddValue("prev_rating", "0");
            data.AddValue("directPost", "1");
            data.AddValue("r_story_value", "76");
            data.AddValue("r_acting_value", "96");
            data.AddValue("r_direction_value", "84");
            data.AddValue("r_visuals_value", "90");
            data.AddValue("r_overall_value", "84");
            data.AddValue("subj", reviewData.ReviewTitle);
            data.AddValue("text", reviewData.ReviewText);
            string result = communications.PerformPost("http://movies.yahoo.com/mvc/pprv?subType=Post", data);

            return result.Contains("You have already reviewed this movie") ? ReviewResult.Successful : ReviewResult.Failed;
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            Storage.DomainSpins = richTextBoxDomain.Text;
            Storage.MovieID = comboBoxMovieID.Text;
            if (comboBoxMovieID.Text != "")
            {
                foreach (var x in Storage.Data)
                {
                    if (x[0] == Storage.MovieID)
                    {
                        Storage.Data.Remove(x);
                        break;
                    }
                }
                Storage.Data.Add(new string[] { Storage.MovieID, textBoxTitle.Text, textBoxReview.Text });
            }
            Storage.Save();
            UpdateStatus("Saved");
        }

        private void comboBoxMovieID_DropDown(object sender, EventArgs e)
        {
            comboBoxMovieID.Items.Clear();
            foreach (var t in Storage.Data)
            {
                comboBoxMovieID.Items.Add(t[0]);
            }
        }

        void LoadItemFromID()
        {
            foreach (var x in Storage.Data)
            {
                if (x[0] == comboBoxMovieID.Text)
                {
                    textBoxTitle.Text = x[1];
                    textBoxReview.Text = x[2];
                }
            }
        }

        private void comboBoxMovieID_TextChanged(object sender, EventArgs e)
        {
            LoadItemFromID();
        }

        private void buttonClearEntry_Click(object sender, EventArgs e)
        {
            foreach (var x in Storage.Data)
            {
                if (x[0] == comboBoxMovieID.Text)
                {
                    Storage.Data.Remove(x);
                    break;
                }
            }
            comboBoxMovieID.Text = "";
            textBoxReview.Clear();
            textBoxTitle.Clear();
            UpdateStatus("Entry removed");
        }

        private void label4_Click(object sender, EventArgs e)
        {
            label4.Text = GetDomainSpin();
            Clipboard.SetText(label4.Text);
        }

    }
}
